跳到主要内容

webpack 构建优化

开发阶段

热更新

它允许在运行时更新所有类型的模块,而无需完全刷新。

module.exports = {
plugins: [new webpack.HotModuleReplacementPlugin()],
devServer: {
hot: true,
},
}

构建阶段

几个大方向入手:缓存、多核、抽离以及拆分

缓存

babel-loader

loader 的编译结果写入硬盘缓存,再次构建如果文件没有发生变化则会直接拉取缓存。可以通过设置 cacheDirectory 来开启缓存。

cache-loader

它所做的事情,就是 babel-loader 开启 cache 后做的事情

uglifyjs-webpack-plugin

代码压缩阶段,也可以通过缓存解决大部分问题。我们可以通过开启 cache 配置开启我们的缓存功能,也可以通过开启 parallel 开启多核编译功能。

代码示例:

module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
}),
],
},
}

多核构建

可能在 webpack 中已经内置了该功能,有待继续研究!

抽离

对于一些不常变更的静态依赖,比如我们项目中常见的 React 全家桶、lodash 等等,我们不希望这些依赖被集成进每一次构建逻辑中,因此,我们会设法将这些静态依赖从每一次的构建逻辑中抽离出去,以提升我们每次构建的构建效率。

常见的方案有两种

  1. webpack-dll-plugin

在首次构建时候就将这些静态依赖单独打包,后续只需要引用这个早就被打好的静态依赖包即可,有点类似“预编译”的概念

  1. externals

我们将这些不需要打包的静态资源从构建逻辑中剔除出去,而使用 CDN 的方式,去引用它们。

拆分

入口拆分

在一个多页应用中,有多个 entry 的前提下,有时候我们只是更改了一个 entry 下的文件,但是却要对所有 entry 执行一遍构建,优化方案

  1. 每一个子模块都被拆分成了一个单独的仓库中,单独构建

  2. 集群编译

集群编译

这里的集群当然不是指我们的真实物理机,而是我们的 docker。其原理就是将单个 entry 剥离出来维护一个独立的构建流程,并在一个容器内执行,待构建完成后,将生成文件打进指定目录。

为什么能这么做呢?因为我们知道,webpack 会将一个 entry 视为一个 chunk,并在最后生成文件时,将 chunk 单独生成一个文件,

模块拆分

在 Webpack4 中移除了我们此前常用的 CommonsChunkPlugin 插件,取而代之的是 splitChunkssplitChunks 的默认配置已经足够我们日常使用,没有特殊需求可以不必特意处理。 我们此处的配置如下(生产环境):

optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
// 可能会增加构建时间
// styles: {
// name: 'index',
// test: /.stylus|css$/,
// chunks: 'all',
// enforce: true
// }
}
}
}

其中,commons 部分的作用是分离出 node_modules 中引入的模块,styles 部分则是合并 CSS 文件。

优化模块查找路径

module.exports = {
exclude: /node_modules/, // 排除不处理的目录
include: path.resolve(__dirname, 'src') // 精确指定要处理的目录
resolve: {
// 用于配置 webpack 去哪些目录下寻找第三方模块
modules: [path.resolve(__dirname, 'node_modules')],
// 过别名来把原导入路径映射成一个新的导入路径,减少耗时的递归解析操作
alias: {
'api': resolve('src/api') // 创建别名
}
}
}

构建结果

  1. 区分构建环境。webpack 生产环境的构建自带一些优化。
  2. 压缩。包括 js、css 代码,以及 gzip 压缩。
  3. 开启 tree-shaking。
  4. 注意 source-map 类型。生产环境一般不需要。

构建打点

speed-measure-webpack-plugin

它能够测量出在你的构建过程中,每一个 Loader 和 Plugin 的执行时长,官方给出的效果图是下面这样:

speed-measure-webpack-plugin

构建分析

输出 Webpack 构建信息的.json 文件

webpack --profile --json > stats.json

web 可视化查看构建分析

有两种方式:

  1. 通过可视化分析工具,是个在线 Web 应用,上传 stats.json 文件就可以
  1. 使用插件 Webpack Bundle Analyzer

其他

progress-bar-webpack-plugin

能为你展示构建进度的 Plugin。效果图:

progress-bar-webpack-plugin

webpack-build-notifier

在你构建完成时,能够像微信、Lark 这样的 APP 弹出消息的方式,提示你构建已经完成了。效果图:

webpack-build-notifier

webpack-dashboard

如果你对 webpack 原始的构建输出不满意的话,也可以使用这样一款 Plugin 来优化你的输出界面。效果图

webpack-dashboard